package cn.stazxr.pool;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @author talentestors
 * @version 1.0
 * @since 2025.05.21
 **/
@SuppressWarnings("unchecked")
public class BaseDaoPlusImpl<T> implements BaseDaoPlus<T> {

	private static final Logger log = LoggerFactory.getLogger(BaseDaoPlusImpl.class);

	protected static DataSource DATASOURCE = null;

	private final Class<T> clazz;

	static {
		Properties properties = new Properties();
		try {
			properties.load(PoolTest.class.getClassLoader().getResourceAsStream("jdbc.properties"));
		} catch (IOException e) {
			log.error(e.getMessage());
		}
		try {
			DATASOURCE = DruidDataSourceFactory.createDataSource(properties);
		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}

	public BaseDaoPlusImpl() {
		// 获取当前实例的直接父类的泛型参数
		ParameterizedType pt = (ParameterizedType) getClass().getGenericSuperclass();
		this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
	}

	protected void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (Exception e) {
				log.error(e.getMessage());
			}
		}
		if (statement != null) {
			try {
				statement.close();
			} catch (Exception e) {
				log.error(e.getMessage());
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (Exception e) {
				log.error(e.getMessage());
			}
		}
	}

	@Override
	public int save(T entity) {
		Connection connection = null;
		PreparedStatement statement = null;
		try {
			// 1、定义sql
			String tName = clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1).toLowerCase();
			Field[] fields = clazz.getDeclaredFields();
			StringBuilder sql = new StringBuilder();
			sql.append("insert into ")
					.append(tName)
					.append(" values(");
			sql.append("?,".repeat(fields.length));
			sql.deleteCharAt(sql.length() - 1);
			sql.append(")");
			log.debug(sql.toString());
			// 2、获取连接
			connection = DATASOURCE.getConnection();
			// 3、预编译sql
			statement = connection.prepareStatement(sql.toString());
			// 4、设置参数
			int idx = 1;
			for (Field field : fields) {
				field.setAccessible(true);
				Object value = field.get(entity);
				statement.setObject(idx++, value);
			}
			// 5、执行sql
			return statement.executeUpdate();
		} catch (SQLException | IllegalAccessException e) {
			log.error(e.getMessage());
		} finally {
			closeAll(connection, statement, null);
		}
		return -1;
	}

	@Override
	public int deleteById(Object id) {
		Connection connection = null;
		PreparedStatement statement = null;
		try {
			// 1、定义sql
			String tName = clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1).toLowerCase();
			StringBuilder sql = new StringBuilder();
			sql.append("delete from ").append(tName).append(" where id = ?");
			log.debug(sql.toString());
			// 2、获取连接
			connection = DATASOURCE.getConnection();
			// 3、预编译sql
			statement = connection.prepareStatement(sql.toString());
			// 4、设置参数
			statement.setObject(1, id);
			// 5、执行sql
			return statement.executeUpdate();
		} catch (SQLException e) {
			log.error(e.getMessage());
		} finally {
			closeAll(connection, statement, null);
		}
		return -1;
	}

	@Override
	public List<T> findAll() {
		Connection connection = null;
		PreparedStatement statement = null;
		ResultSet resultSet = null;
		List<T> list = new ArrayList<>();
		try {
			// 1、定义sql
			String tName = clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1).toLowerCase();
			StringBuilder sql = new StringBuilder();
			sql.append("select * from ").append(tName);
			log.debug(sql.toString());
			// 2、获取连接
			connection = DATASOURCE.getConnection();
			// 3、预编译sql
			statement = connection.prepareStatement(sql.toString());
			// 4、执行sql
			resultSet = statement.executeQuery();
			// 5、处理结果集
			while (resultSet.next()) {
				try {
					T entity = clazz.getDeclaredConstructor().newInstance();
					for (Field field : clazz.getDeclaredFields()) {
						field.setAccessible(true);
						Object value = resultSet.getObject(field.getName());
						field.set(entity, value);
					}
					list.add(entity);
				} catch (IllegalAccessException | InvocationTargetException | InstantiationException |
				         NoSuchMethodException e) {
					log.error(e.getMessage());
				}
			}
		} catch (SQLException e) {
			log.error(e.getMessage());
		} finally {
			closeAll(connection, statement, resultSet);
		}
		return list;
	}

	@Override
	public T findById(Object id) {
		Connection connection = null;
		PreparedStatement statement = null;
		ResultSet resultSet = null;
		try {
			// 1、定义sql
			String tName = clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1).toLowerCase();
			StringBuilder sql = new StringBuilder();
			sql.append("select * from ").append(tName).append(" where id = ?");
			log.debug(sql.toString());
			// 2、获取连接
			connection = DATASOURCE.getConnection();
			// 3、预编译sql
			statement = connection.prepareStatement(sql.toString());
			// 4、设置参数
			statement.setObject(1, id);
			// 5、执行sql
			resultSet = statement.executeQuery();
			// 6、处理结果集
			if (resultSet.next()) {
				try {
					T entity = clazz.getDeclaredConstructor().newInstance();
					for (Field field : clazz.getDeclaredFields()) {
						field.setAccessible(true);
						Object value = resultSet.getObject(field.getName());
						field.set(entity, value);
					}
					return entity;
				} catch (IllegalAccessException | InvocationTargetException | InstantiationException |
				         NoSuchMethodException e) {
					log.error(e.getMessage());
				}
			}
		} catch (SQLException e) {
			log.error(e.getMessage());
		} finally {
			closeAll(connection, statement, resultSet);
		}
		return null;
	}

	@Override
	public int update(T entity) {
		Connection connection = null;
		PreparedStatement statement = null;
		try {
			// 1、定义sql
			String tName = clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1).toLowerCase();
			Field[] fields = clazz.getDeclaredFields();
			StringBuilder sql = new StringBuilder();
			sql.append("update ").append(tName).append(" set ");
			for (Field field : fields) {
				sql.append(field.getName()).append(" = ?,");
			}
			sql.deleteCharAt(sql.length() - 1);
			sql.append(" where id = ?");
			log.debug(sql.toString());
			// 2、获取连接
			connection = DATASOURCE.getConnection();
			// 3、预编译sql
			statement = connection.prepareStatement(sql.toString());
			// 4、设置参数
			int idx = 1;
			for (Field field : fields) {
				field.setAccessible(true);
				Object value = field.get(entity);
				statement.setObject(idx++, value);
			}
			statement.setObject(idx, entity.getClass().getDeclaredField("id").get(entity));
			// 5、执行sql
			return statement.executeUpdate();
		} catch (SQLException | IllegalAccessException | NoSuchFieldException e) {
			log.error(e.getMessage());
		} finally {
			closeAll(connection, statement, null);
		}
		return -1;
	}
}
